package com.qire.common.utils;

import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import androidx.annotation.RequiresApi;

/**
 * 修改Activity相关主题状态的工具，如：状态栏主题修改，横纵屏修改，等等相关。
 */
public final class ThemeUtil {

    private static final int MIUI = 1;
    private static final int FLYME = 2;
    private static final int ANDROID_NATIVE = 3;
    private static final int NA = 4;

    /** 状态栏处理方案类型 */
    private final static int StatusBarHandleType = getStatusBarHandleType();

    private ThemeUtil() {
        throw new UnsupportedOperationException("不能初始化这个工具");
    }

    /**
     * @return 获取状态栏处理方案类型
     */
    public static int getStatusBarHandleType() {
        switch (OSUtil.currentSystemType()) {
            case MI_UI_V6:
                return MIUI;
            case MI_UI_V7:
                //开发版 7.7.13 及以后版本采用了系统API，旧方法无效但不会报错
                return ANDROID_NATIVE;
            case FLY_ME_V4:
                return FLYME;
            case ANDROID_V23:
                return ANDROID_NATIVE;
            default:
                return NA;
        }
    }

    //region    #状态栏字体主题 begin

    /**
     * 修改状态栏字体颜色，高亮或深暗
     * @param activity   目标Activity
     * @param dark       true 字体颜色为黑色，false为白色
     * @param isFullMode 是否在全屏模式下
     */
    public static void changeStatusBarLightOrDark(final Activity activity, final boolean dark, boolean isFullMode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            switch (StatusBarHandleType) {
                case MIUI:
                    MIUISetStatusBarLightMode(activity, dark);
                    break;
                case FLYME:
                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
                        setAndroidNativeLightStatusBar(activity, dark, isFullMode);
                    } else {
                        setFlymeLightStatusBar(activity, dark);
                    }
                    break;
                case ANDROID_NATIVE:
                    setAndroidNativeLightStatusBar(activity, dark, isFullMode);
                    break;
                case NA:
                    // N/A do nothing
                    break;
            }
        }
    }

    /**
     * 修改状态栏字体颜色，高亮或深暗
     * @param window 目标Window
     * @param dark      true 字体颜色为黑色，false为白色
     * @param isFullMode 是否在全屏模式下
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static void changeStatusBarLightOrDark(final Window window, final boolean dark, boolean isFullMode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            switch (StatusBarHandleType) {
                case MIUI:
                    MIUISetStatusBarLightMode(window, dark);
                    break;
                case FLYME:
                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
                        setAndroidNativeLightStatusBar(window, dark, isFullMode);
                    } else {
                        setFlymeLightStatusBar(window, dark);
                    }
                    break;
                case ANDROID_NATIVE:
                    setAndroidNativeLightStatusBar(window, dark, isFullMode);
                    break;
                case NA:
                    // N/A do nothing
                    break;
            }
        }
    }

    /**
     * 需要MIUIV6以上
     *
     * @param dark 是否把状态栏文字及图标颜色设置为深色
     * @return boolean 成功执行返回true
     */
    private static void MIUISetStatusBarLightMode(Object object, boolean dark) {
        Window window = null;
        if (object instanceof Activity) {
            window = ((Activity) object).getWindow();
        } else if (object instanceof Window) {
            window = (Window) object;
        }

        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && OSUtil.SystemType.MI_UI_V7.isAboveVersion()) {
                    //开发版 7.7.13 及以后版本采用了系统API，旧方法无效但不会报错，所以两个方式都要加上
                    if (dark) {
                        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
                    } else {
                        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                    }
                }

            } catch (Exception ignore) {

            }
        }
    }

    /**
     * 用谷歌原生设置状态栏文字颜色的方法进行设置的话，因为一直会携带SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN这个flag，那么默认界面会变成全屏模式，
     * 需要在根布局中设置FitsSystemWindows属性为true, content.setFitsSystemWindows(true) 或添加 android:fitsSystemWindows="true" 到XML根
     * @param obj 目标
     * @param dark true 字体颜色为黑色，false为白色
     * @param isFullMode 是否在全屏模式下
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    private static void setAndroidNativeLightStatusBar(Object obj, boolean dark, boolean isFullMode) {
        View decor = null;
        if (obj instanceof Activity) {
            decor = ((Activity) obj).getWindow().getDecorView();
        } else if (obj instanceof Window) {
            decor = ((Window) obj).getDecorView();
        }

        if (decor == null) {
            return;
        }

        if (dark) {
            if (isFullMode) {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            }
        } else {
            // We want to change tint color to white again.
            // You can also record the flags in advance so that you can turn UI back completely if
            // you have set other flags before, such as translucent or full screen.
            if (isFullMode) {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            } else {
                decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            }
        }
    }

    private static boolean setFlymeLightStatusBar(Object obj, boolean dark) {
        boolean result = false;
        Window window = null;
        if (obj instanceof Activity) {
            window = ((Activity) obj).getWindow();
        } else if (obj instanceof Window) {
            window = ((Window) obj);
        }

        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception ignore) {
            }
        }
        return result;
    }

    //endregion #状态栏字体主题 end

    /**
     * 修改状态栏为全透明
     */
    public static void transparencyBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 修改状态栏颜色
     */
    public static void setStatusBarColor(Activity activity, int colorId) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(activity.getResources().getColor(colorId,null));
        }
    }

    //region    #窗口对齐样式 begin
    /**
     * 设置 Dialog 样式的 Activity 调整到底部对齐并铺满全屏的样式。
     * @param activity
     * @param height 高度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     */
    public static void setWindowGravityBottom(Activity activity, int height) {
        setWindowGravityBottom(activity.getWindow(), height);
    }

    /**
     * 设置 Dialog 样式的 Activity 调整到底部对齐并铺满全屏的样式。
     * @param activity
     * @param dimAmount 背景暗度值
     */
    public static void setWindowGravityBottom(Activity activity, float dimAmount) {
        setWindowGravityBottom(activity.getWindow(), dimAmount);
    }

    /**
     * 设置窗口宽度铺满底部对齐，用于 Dialog 样式调整到底部菜单样式。
     * @param window 窗口对象实体
     * @param height 高度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     */
    public static void setWindowGravityBottom(Window window, int height) {
        setWindowGravityBottom(window, window.getAttributes().dimAmount, height);
    }

    /**
     * 设置窗口宽度铺满底部对齐，用于 Dialog 样式调整到底部菜单样式。
     * @param window 窗口对象实体
     * @param dimAmount 暗度值 0f~1f 之间。
     */
    public static void setWindowGravityBottom(Window window, float dimAmount) {
        setWindowGravityBottom(window, dimAmount, WindowManager.LayoutParams.MATCH_PARENT);
    }

    /**
     * 设置窗口宽度铺满底部对齐，用于 Dialog 样式调整到底部菜单样式。
     * @param window 窗口对象实体
     * @param dimAmount 暗度值 0f~1f 之间。
     * @param height 高度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     */
    public static void setWindowGravityBottom(Window window, float dimAmount, int height) {
        setWindowGravityBottom(window, dimAmount, WindowManager.LayoutParams.MATCH_PARENT, height);
    }

    /**
     * 设置窗口宽度铺满底部对齐，用于 Dialog 样式调整到底部菜单样式。不是全屏的窗口超出部分讲收 dialog 样式影响成为触碰关闭的区域。
     * @param window 窗口对象实体
     * @param dimAmount 暗度值 0f~1f 之间。
     * @param width 宽度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     * @param height 高度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     */
    public static void setWindowGravityBottom(Window window, float dimAmount, int width, int height) {
        setWindowAttributes(window, Gravity.BOTTOM, dimAmount, width, height);
    }

    /**
     * 设置填满窗口
     * @param window 窗口实体对象
     */
    public static void setWindowFull(Window window) {
        WindowManager.LayoutParams attributes = window.getAttributes();
        setWindowAttributes(window, attributes.gravity, attributes.dimAmount, -1, -1);
    }

    /**
     * 设置窗口样式属性，用于 dialog 样式属性调整。
     * @param window 窗口对象实体
     * @param gravity 对齐位置
     * @param dimAmount 暗度值 0f~1f 之间。
     * @param width 宽度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     * @param height 高度，默认值是MATCH_PARENT；您可以将它们更改为WRAP_CONTENT或绝对值，以使窗口不是全屏显示。
     */
    public static void setWindowAttributes(Window window, int gravity, float dimAmount, int width, int height) {
        window.setGravity(gravity);
        window.setDimAmount(dimAmount);
        window.setLayout(width, height);
    }
    //endregion #窗口对齐样式 end

}
